package com.sojson.config.filter.interfaces.impl;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.servlet.ServletRequest;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sojson.constant.Constant;
import com.sojson.util.StringUtil;
import com.sojson.util.encryption.EncryptionUtil;
import com.sojson.util.json.JsonUtil;
import com.sojson.util.text.Convert;

/**
 * 自定义获取参数(为了对参数进行修改: 解密?)
 * 
 * @author liu
 * @date 2020-11-02
 */
public class CustomParamDecryHttpServletRequestWrapper extends CustomParamHttpServletRequestWrapper {

    /** 对传过来的参数进行解密的密钥(不写为没有密钥) */
    public static final String PARAM_DECRYPTION_KEY =
        Convert.toStr(Constant.PROPERTIES.getProperty("so.application.filter.paramDecryption.key"), null);
    public static final String DATA =
        Convert.toStr(Constant.PROPERTIES.getProperty("so.application.filter.paramDecryption.paramName"), "data");
    /** 普通参数所有参数的Map集合 */
    private Map<String, String[]> parameterMap;

    /**
     * 每次请求都会从这里获取参数
     * 
     * @param request
     * @throws IOException 
     */
    public CustomParamDecryHttpServletRequestWrapper(ServletRequest request) throws IOException {
        super(request);
        filterSpecialCharacter(request.getParameter(CustomParamDecryHttpServletRequestWrapper.DATA));
        byte[] requestBody = getRequestBody();
        setRequestBody(decryption(requestBody, CustomParamDecryHttpServletRequestWrapper.PARAM_DECRYPTION_KEY));
        // 保证不为空
        if (isBlankObject(requestBody)) {
            setRequestBody(new byte[0]);
        }
    }

    /**
     * Controller绑定普通参数的时候会从这里获取
     * 
     * 然后执行getParameterNames()获取所有name,然后执行多次getParameterValues(name)获取值
     */
    @Override
    public String getParameter(String key) {
        String[] arr = getParameterMap().get(key);
        return isNotBlankObject(arr) ? arr.length > 0 ? arr[0] : null : null;
    }

    /**
     * 获取所有参数名
     *
     * @return 返回所有参数名
     */
    @Override
    public Enumeration<String> getParameterNames() {
        Vector<String> vector = new Vector<>(getParameterMap().keySet());
        return vector.elements();
    }

    /**
     * 获取指定参数名的所有值的数组,比如checkobx类型,单个数值类型的数组长度为1
     */
    @Override
    public String[] getParameterValues(String name) {
        return getParameterMap().get(name);
    }

    /**
     * 获取Map集合
     */
    @Override
    public Map<String, String[]> getParameterMap() {
        return parameterMap;
    }

    /**
     * 设置Map集合
     * 
     * @param parameterMap
     */
    public void setParameterMap(Map<String, String[]> parameterMap) {
        this.parameterMap = parameterMap;
    }

    /**
     * 如果参数存在,就把所有参数放到Map集合,以后就从这个Map中获取参数
     * 
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    private void filterSpecialCharacter(String value) {
        // 如果参数不存在就创建一个空的Map集合
        if (isBlank(value)) {
            setParameterMap(new HashMap<>(0));
            return;
        }

        // 解密
        String decryption =
            decryption(value.replaceAll(" ", "+"), CustomParamDecryHttpServletRequestWrapper.PARAM_DECRYPTION_KEY);
        HashMap<String, String[]> jsonToObject = JsonUtil.jsonToObject(decryption, HashMap.class);
        // 放到Map集合
        setParameterMap(jsonToObject);
        Set<String> keySet = jsonToObject.keySet();
        // 因为有的参数可能是Checkbox类型的,所以就要分情况添加到Map中
        for (String string : keySet) {
            Object object = jsonToObject.get(string);
            if (object instanceof String) {
                jsonToObject.put(string, new String[] {(String)object});
            } else if (object instanceof JSONArray) {
                jsonToObject.put(string, JSONObject.parseObject(object.toString(), String[].class));
            } else {
                jsonToObject.put(string, new String[] {String.valueOf(object)});
            }
        }
    }

    /**
     * 判断一个对象是否不是空(空对象)
     * 
     * @param obj
     * @return
     */
    private boolean isBlankObject(Object obj) {
        return StringUtil.isBlankObject(obj);
    }

    /**
     * 判断一个对象是否不是空(空对象)
     * 
     * @param obj
     * @return
     */
    private boolean isNotBlankObject(Object obj) {
        return StringUtil.isNotBlankObject(obj);
    }

    /**
     * 判断一个字符串是否不是空
     * 
     * @param obj
     * @return
     */
    private boolean isBlank(String str) {
        return StringUtil.isBlank(str);
    }

    /**
     * 解密方法
     * 
     * @param inStr
     * @param key 解密密钥
     * @return
     */
    private String decryption(String inStr, String key) {
        return EncryptionUtil.decryption(inStr, key);
    }

    /**
     * 解密方法
     * 
     * @param inStr
     * @param key 解密密钥
     * @return
     */
    private byte[] decryption(byte[] inStr, String key) {
        return EncryptionUtil.decryption(inStr, key);
    }

}